import '../style/visual.less';
// @ts-ignore
import * as echarts from 'echarts';
import { myTooltipC } from './myTooltip.js';
import "echarts/map/js/china.js";
import "echarts/map/js/world.js";
import "echarts/map/js/province/anhui.js";
import "echarts/map/js/province/aomen.js";
import "echarts/map/js/province/beijing.js";
import "echarts/map/js/province/chongqing.js";
import "echarts/map/js/province/fujian.js";
import "echarts/map/js/province/gansu.js";
import "echarts/map/js/province/guangdong.js";
import "echarts/map/js/province/guangxi.js";
import "echarts/map/js/province/guizhou.js";
import "echarts/map/js/province/hainan.js";
import "echarts/map/js/province/hebei.js";
import "echarts/map/js/province/heilongjiang.js";
import "echarts/map/js/province/henan.js";
import "echarts/map/js/province/hubei.js";
import "echarts/map/js/province/hunan.js";
import "echarts/map/js/province/jiangsu.js";
import "echarts/map/js/province/jiangxi.js";
import "echarts/map/js/province/jilin.js";
import "echarts/map/js/province/liaoning.js";
import "echarts/map/js/province/neimenggu.js";
import "echarts/map/js/province/ningxia.js";
import "echarts/map/js/province/qinghai.js";
import "echarts/map/js/province/shandong.js";
import "echarts/map/js/province/shanghai.js";
import "echarts/map/js/province/shanxi.js";
import "echarts/map/js/province/shanxi1.js";
import "echarts/map/js/province/sichuan.js";
import "echarts/map/js/province/taiwan.js";
import "echarts/map/js/province/tianjin.js";
import "echarts/map/js/province/xianggang.js";
import "echarts/map/js/province/xinjiang.js";
import "echarts/map/js/province/xizang.js";
import "echarts/map/js/province/yunnan.js";
import "echarts/map/js/province/zhejiang.js";
import geoCoordMap from './geoCoordMap.json';
var _;
let myChart;
let rawData;
let isTooltipModelShown = false;
const clickLeftMouse = 0;
const clickRightMouse = 2;
const locationReg = /(省|市|自治区|自治州|县|区)/g;
const image = {
  pyramid : 'image://',
  water: []
}
const getImage = (host, name) => {
  return `image://${host.assetsManager.getImage(name)}`
}
export default class Visual extends WynVisual {
  private container: HTMLDivElement;
  private host: any;
  private isMock: boolean;
  private firstRender: boolean;
  private bindCoords: boolean;
  private valuesName: string;
  private locationName: string;
  private toolTipName: string [];
  private longitudeName: string;
  private latitudeName: string;
  private properties: any;
  private resultData: any;
  private locationArr: any;
  private shadowDiv: any;
  private format: any;
  private displayUnit: any;
  private items: any;
  private timeInterval: any;
  private config: any;
  private myTooltip: any;
  private preview: boolean;
  private selectionManager: any;
  private selection: any[] = [];
  private timer: any;
  private timerId = null;
  
  constructor(dom: HTMLDivElement, host: VisualNS.VisualHost, options: VisualNS.IVisualUpdateOptions) {
    super(dom, host, options);
    [].push.call(image.water, getImage(host, 'image1'), getImage(host, 'image2'), getImage(host, 'image3'));
    this.container = dom;
    this.host = host;
    this.isMock = true;
    this.bindCoords = false;
    this.preview = false;
    this.selectionManager = host.selectionService.createSelectionManager();
    _ = host.moduleManager.getModule('lodash');

    myChart = echarts.init(dom, null, { renderer: 'canvas' });
    // myChart = echarts.init(dom, null ,{ renderer: 'svg'});
    this.shadowDiv = document.createElement("div");
    this.container.appendChild(this.shadowDiv);
    this.container.style.transform = 'rotate3d(-70, -1, 0, -45deg)';
    this.container.firstElementChild.setAttribute('style', 'height : 0');
    
    this.config = {
      priority: 'top',        // 默认在点上方OR下方（top/bottom）
      partition: 2,         // 左右分割比例
      lineColor: 'rgba(253, 129, 91, 0.8)',      // 引导线颜色
      offset: [5, 5],
      L1: {
        time: 0.2,          // L1动画时长(单位s)
        long: 40            // L1长度
      },
      L2: {
        time: 0.2,
        long: 40
      }
    }
    this.myTooltip = new myTooltipC(dom, this.config);
    rawData = [
      {
        name: '北京',
        value: [116.405285, 39.904989],
        datas: 1354,
        img: image.water[0],
      },
      {
        name: '陕西省',
        value: [108.948024, 34.263161],
        datas: 1402,
        img: image.water[1],
      },
      {
        name: '上海',
        value: [121.472644, 31.231706],
        datas: 2468,
        img: image.water[2],
      },
      {
        name: '成都市',
        value: [104.065735, 30.659462],
        datas: 768,
        img: image.water[0],
      },
      {
        name: '武汉市',
        value: [114.298572, 30.584355],
        datas: 589,
        img: image.water[1],
      },
      {
        name: '福州市',
        value: [119.306239, 26.075302],
        datas: 1500,
        img: image.water[2],
      },
    ];
    this.firstRender = true;
  }
  private dispatch = (type, payload) => myChart.dispatchAction({ ...payload, type });

  private mouseDownHandler = (e: any) => {
    e.stopPropagation();
    this.host.contextMenuService.hide();
    if (!e.seriesClick) {
      // clear tooltip
      this.hideTooltip();
      return;
    }
  }

  private contextmenuFunction = (params) => {
    params.preventDefault();
    params.stopPropagation();
      this.host.contextMenuService.show({
        position: {								//跳转的selectionsId(左键需要)
          x: params.x,
          y: params.y,
        }
      })
      return;
  }

  public autoPlayTimer = () => {
    this.timeInterval = [];
    const timerPlay = () => {
      let index = 0;
      let dataLength = this.items.length;
      clearInterval(this.timer);
      this.timer = setInterval(() => {
        if (this.timer !==  this.timeInterval[this.timeInterval.length - 1]) {
          return clearInterval(this.timer);
        }
        const name = this.items[index].name.replace(locationReg,'')
        const autoStopInfo = {
          seriesIndex: 0,
          // dataIndex: index,
          name,
        };
       
        this.dispatch('downplay', autoStopInfo)
        index++;
        if (index >= dataLength) {
          index = 0;
          // this.timeInterval.map(_timer => clearInterval(_timer))
          clearInterval(this.timer)
        }
        const nameText = this.items[index].name.replace(locationReg, '')
        const autoInfo = {
          seriesIndex: 0,
          // dataIndex: index,
          name: nameText,
        };
        this.dispatch('highlight', autoInfo)
        this.dispatch('showTip', autoInfo)
      }, (Number(this.properties.rotationInterval) * 1000));
      this.timeInterval.push(this.timer);
    }

    myChart.on('mousemove', (e) => {
        clearInterval(this.timer);
        myChart.dispatchAction({
        type: "showTip",
        seriesIndex: 0,
        dataIndex: e.dataIndex
      });
    })

    timerPlay();
    this.container.addEventListener('mouseenter', (e: any) => {
      clearInterval(this.timer)
      this.items.forEach((element, index) => {
        const name = element.name.replace(locationReg,'')
        const selectInfo = {
          seriesIndex: 0,
          // dataIndex: index,
          name: name,
        };
        this.dispatch('downplay',selectInfo)
      });
    })
    this.container.addEventListener('mouseleave', (e: any) => {
      if (this.timer) clearInterval(this.timer);
      timerPlay();
    })
  }

  private hideTooltip = () => {
    this.host.contextMenuService.hide();
    isTooltipModelShown = false;
  }

  public getNodeSelectionId = (label: any) => {
    const _target = this.items.find((_item: any) => {
      const name = _item.name.replace(locationReg, '');
      return name === label && _item;
    })
    return _target && _target.selectionId || {}
  }

  public bindEvents = () => {
    this.container.addEventListener('click', this.mouseDownHandler);

    myChart.on('mouseover',(params)=> {
      const selectInfo = {
        seriesIndex: params.seriesIndex,
        dataIndex: params.dataIndex,
      };
      this.dispatch('highlight',selectInfo)
    })

    myChart.on('mouseout', (params) => {
      const selectInfo = {
        seriesIndex: params.seriesIndex,
        dataIndex: params.dataIndex,
      };
      this.dispatch('downplay',selectInfo)
    })
    myChart.off('mouseup')
    myChart.on('mouseup', (params) => {
      const clickMouse = params.event.event.button;
      if (params.componentType !== 'series') return;
      params.event.event.seriesClick = true;
      const selectionId = this.getNodeSelectionId(params.name);
      const selectInfo = {
        seriesIndex: params.seriesIndex,
        dataIndex: params.dataIndex,
      }; 
      if (selectionId) {
        if (!this.selectionManager.contains(selectionId)) {
          this.selectionManager.select(selectionId, true);
          this.dispatch('highlight', selectInfo);
          this.selection.push(selectInfo);
        } else {
          this.selectionManager.clear(selectionId);
        }
        if (clickMouse === clickLeftMouse) {
          if (this.properties.clickLeftMouse === 'none' || this.properties.clickLeftMouse === 'showToolTip') {
            return
          } else {
            if (isTooltipModelShown) return;
            this.hideTooltip();
            const selectionIds = this.selectionManager.getSelectionIds();
            this.host.commandService.execute([{
              name: this.properties.clickLeftMouse,
              payload: {
                selectionIds,
                position: {
                  x: params.event.event.clientX,
                  y: params.event.event.clientY,
                  },
              }
            }])
          }
        } else if (clickMouse === clickRightMouse) {  
          params.event.event.preventDefault();
          const showTooltip = _.debounce((params, asModel = false) => {
            if (asModel) isTooltipModelShown = true;
            this.host.contextMenuService.show({
              position: {
                x: params.clientX,
                y: params.clientY,
              }
            })
          });
          showTooltip(params.event.event, true);
        }
      }
      
    })
    
    this.container.addEventListener('contextmenu', this.contextmenuFunction);
  }

  private getCoords = (keyWord: string) => {
    let reg = new RegExp(keyWord);
    for (let i = 0; i < geoCoordMap.length; i++) {
      if (reg.test(geoCoordMap[i].name)) {
        return [geoCoordMap[i].lng, geoCoordMap[i].lat];
      }
    }
  }
  private getSelectionId = (_item, dimension) => {
    const selectionId = this.createSelectionId();
    // profile.location.values[0]
    this.locationName && selectionId.withDimension(dimension , _item);
    return selectionId
  }
  private prepareData(data: any, profile: any) {
    return data.map((item, index) => {
      let geoCoord = this.bindCoords ? [item[this.longitudeName], item[this.latitudeName]] : this.getCoords(item[this.locationName]);
      const toolTip = this.toolTipName.map((_item: string) => { return { [_item]: item[_item]}});
      return {
          name: item[this.locationName],
          value: geoCoord,
          datas: item[this.valuesName],
          img: image.water[index % 3],
          toolTip: toolTip,
          selectionId:  this.getSelectionId(item, profile.location.values[0])
      }
    })
  }
  createSelectionId = (sid?) => this.host.selectionService.createSelectionId(sid);
  public update(options: VisualNS.IVisualUpdateOptions) {
    this.locationArr = [];
    this.preview = options.isViewer
    this.isMock = !options.dataViews.length;
    if (!this.isMock) {
      let profile = options.dataViews[0].plain.profile;
      let bindData = options.dataViews[0].plain.data;
      this.valuesName = profile.values.values[0].display;
      this.locationName = profile.location.values[0].display;
      this.toolTipName = profile.tooltipFields.values.map((_item) => _item.display);
      this.bindCoords = !!(profile.longitude.values.length && profile.latitude.values.length);
      if(this.bindCoords) {
        this.longitudeName = profile.longitude.values[0].display;
        this.latitudeName = profile.latitude.values[0].display;
      }
      this.resultData = this.prepareData(bindData, profile);
      // data format and display unit
      this.format = options.dataViews[0].plain.profile.values.options.valueFormat;
      this.displayUnit = options.dataViews[0].plain.profile.values.options.valueDisplayUnit;
    }
    this.properties = options.properties;
    let renderData = this.isMock ? rawData : this.resultData;
    this.items = renderData;

    echarts.registerMap('customMap', this.properties.customMap && this.properties.MapJson ? JSON.parse(this.properties.MapJson) : {})
    this.render(renderData);
    this.bindEvents();
  }

  private render(_data) {
    this.host.eventService.renderStart();
    this.container.style.opacity = '1';
    let myTooltip = this.myTooltip;
    myChart.clear();
  
    this.shadowDiv.style.cssText = '';
    let options = this.properties;
    this.shadowDiv.style.cssText = `box-shadow: inset 0 0 ${options.borderShadowBlurLevel}px ${options.borderShadowWidth}px ${options.borderShadowColor}; position: absolute; width: 100%; height: 100%; pointer-events: none; z-index: 1; `;
    // add map background
    //  background: url(${options.mapShadowImage})
    // this.container.style.background = `url(${options.mapShadowImage}) center center no-repeat`;
    // this.container.style.backgroundSize = '100% 100%'
    options.automaticRotation && this.preview && this.autoPlayTimer();
    myTooltip.config['text'] = {
      time: 0.3,
      font: `${options.tooltipTextStyle.fontStyle} ${options.tooltipTextStyle.fontWeight} ${options.tooltipTextStyle.fontSize} ${options.tooltipTextStyle.fontFamily}`,
      color: options.tooltipTextStyle.color,
      padding: [options.tooltipPadding.top, options.tooltipPadding.right, options.tooltipPadding.bottom, options.tooltipPadding.left],
      width: options.tooltipWidth,
      height: options.tooltipHeight,
      lineHeight: 24,
      backgroundColor: options.tooltipBackgroundColor,
      borderColor: options.tooltipBorderColor,
      borderWidth: 1,
      angle: {
        width: 2,
        long: 15
      }
    }
    const formatList = options.mapCollection;
    const isSymBolChart = options.symbolStyle === 'pyramid' || options.symbolStyle === 'water';
    const formatColor = (defaultColor, value) => {
      if (formatList.length > 0) {
        formatList.map((_item: any) => {
            if (value >= Number(_item.minFormatValue) && value <= Number(_item.maxFormatValue)) {
              if (_item.minRank === '[' && _item.maxRank === ']') {
                // _name = `${_item.minFormatValue}To${_item.maxFormatValue}`
                defaultColor = _item.formatColor
              }
            }
            if (value >= Number(_item.minFormatValue) && value < Number(_item.maxFormatValue)) {
              if (_item.minRank === '[' && _item.maxRank === ')') {
                defaultColor = _item.formatColor
              }
            }
            if (value > Number(_item.minFormatValue) && value <= Number(_item.maxFormatValue)) {
              if (_item.minRank === '(' && _item.maxRank === ']') {
                defaultColor = _item.formatColor
              }
            }
            if (value > Number(_item.minFormatValue) && value < Number(_item.maxFormatValue)) {
              if (_item.minRank === '(' && _item.maxRank === ')') {
                defaultColor = _item.formatColor
              }
            }
        })
      }
      return defaultColor;
    }

    const formatLabelColor = () => {
      const _richStyle = {};
      formatList && formatList.map((_item, _index) => {
        _richStyle[`${_item.minFormatValue}To${_item.maxFormatValue}`] = {
          padding: [5, 0],
          color: _item.formatColor,
          fontSize: parseInt(options.labelTextStyle.fontSize.slice(0, -2))
        }
      })
      return _richStyle;
    }

    const labelOptions = () => {
      return {
        normal: {
          show: options.showLabel,
          position: options.symbolStyle === 'water'  || options.symbolStyle === 'pyramid' ? [Number(Math.floor(options.mapSymbolWidth / 2)), -options.tooltipDistance] : 'end',
          borderWidth: 1,
          align: 'center',
          verticalAlign: 'middle',
          borderType: 'solid',
          borderColor: options.tooltipBackgroundType === 'color' ? options.labelBorderColor : options.tooltipBgBorderColor,
          borderRadius: options.tooltipBorderRadius,
          padding: [options.labelPadding.top, options.labelPadding.right, options.labelPadding.bottom, options.labelPadding.left ],
          fontSize: parseInt(options.labelTextStyle.fontSize.slice(0, -2)),
          fontFamily: options.labelTextStyle.fontFamily,
          fontStyle: options.labelTextStyle.fontStyle,
          fontWeight: options.labelTextStyle.fontWeight,
          backgroundColor: options.tooltipBackgroundType === 'color' ? options.labelBackgroundColor : { image: options.tooltipBackgroundImage },
          formatter: (params: any) => {
            let _text = [];
            let value = params.data.datas;
            const _formatRichName = formatList.map((_item: any) => {
              let _name = '';
              if (value >= Number(_item.minFormatValue) && value <= Number(_item.maxFormatValue)) {
                if (_item.minRank === '[' && _item.maxRank === ']') {
                  _name = `${_item.minFormatValue}To${_item.maxFormatValue}`
                }
              }
              if (value >= Number(_item.minFormatValue) && value < Number(_item.maxFormatValue)) {
                if (_item.minRank === '[' && _item.maxRank === ')') {
                  _name = `${_item.minFormatValue}To${_item.maxFormatValue}`
                }
              }
              if (value > Number(_item.minFormatValue) && value <= Number(_item.maxFormatValue)) {
                if (_item.minRank === '(' && _item.maxRank === ']') {
                  _name = `${_item.minFormatValue}To${_item.maxFormatValue}`
                }
              }
              if (value > Number(_item.minFormatValue) && value < Number(_item.maxFormatValue)) {
                if (_item.minRank === '(' && _item.maxRank === ')') {
                  _name = `${_item.minFormatValue}To${_item.maxFormatValue}`
                }
              }
              return _name;
            }).filter(_item => _item)[0] || 'name';
            const _formatTarget = options.useToLabel ? _formatRichName: 'name';
            if (options.showLocation) {
              let name = params.name;
              _text.push(name)
            }
            if (options.showValue) {
              if (this.isMock) {
                value = value;
              } else {
                let realDisplayUnit = this.displayUnit;
                const formatService = this.host.formatService;
                if (formatService.isAutoDisplayUnit(this.displayUnit)) {
                  realDisplayUnit = formatService.getAutoDisplayUnit(value);
                }
                value = formatService.format(this.format, value, realDisplayUnit)
              }
              _text.push(value)
            }
            const _result = _text.join('\n');
            return `{${_formatTarget}|${_result}}`;
          },
          rich:{
            name:{
              padding: [5, 0],
              color: options.labelTextStyle.color,
              fontSize: parseInt(options.labelTextStyle.fontSize.slice(0, -2))
            },
            ...formatLabelColor(),
          }
        }
        }
    }
    
    const lineMaxHeight = (type?: string) => {
      const maxValue = Math.max(...this.items.map(item => item.datas))
      return type ? 14/maxValue : 10/maxValue
    }

    const  RgbToHex  = (a, b, c)  =>{
      var r = /^\d{1,3}$/;
      if (!r.test(a) || !r.test(b) || !r.test(c)) return window.alert("输入错误的rgb颜色值");
      var hexs = [a.toString(16), b.toString(16), c.toString(16)];
      for (var i = 0; i < 3; i++) if (hexs[i].length == 1) hexs[i] = "0" + hexs[i];
      return "#" + hexs.join("");
    }
    
    const  HexToRgb = (str) =>{
      var r = /^\#?[0-9a-f]{6}$/;
      //test方法检查在字符串中是否存在一个模式，如果存在则返回true，否则返回false
      if (!r.test(str)) return ;
      //replace替换查找的到的字符串
      str = str.replace("#", "");
      //match得到查询数组
      var hxs = str.match(/../g);
      //alert('bf:'+hxs)
      for (var i = 0; i < 3; i++) hxs[i] = parseInt(hxs[i], 16);
      return hxs;
    }
    const getLightOrDarkColor = (color, level, isLight?: boolean) => {
      var r = /^\#?[0-9a-f]{6}$/;
      let rgbc = [];
      if (!r.test(color)) {
        var rgb = color.split(',');
        var _r = parseInt(rgb[0].split('(')[1]);
        var _g = parseInt(rgb[1]);
        var _b = parseInt(rgb[2].split(')')[0]);
        rgbc = HexToRgb(RgbToHex(_r, _g, _b));
      } else {
        rgbc = HexToRgb(color);
      }
      if (isLight) {
        for (var i = 0; i < 3; i++) {
          rgbc[i] = Math.floor((255 - rgbc[i]) * level + rgbc[i]);
        }
        return RgbToHex(rgbc[0], rgbc[1], rgbc[2]);
      } else {
        for (var i = 0; i < 3; i++) {
          rgbc[i] = Math.floor(rgbc[i] * (1 - level));
        }
        return RgbToHex(rgbc[0], rgbc[1], rgbc[2]);
      }
    }
    
    const hexToRgba = (hex, opacity?: number, isLine?: boolean) => {
      const isHex = hex.slice(0, 1) === '#';
      const _opacity = isLine ? 0.1 : opacity;
      if (isHex) {
        return 'rgba(' + parseInt('0x' + hex.slice(1, 3)) + ',' + parseInt('0x' + hex.slice(3, 5)) + ','
              + parseInt('0x' + hex.slice(5, 7)) + ',' + _opacity + ')';
      } else {
        // fixed rgba to rgba
        var rgb = hex.split(',');
        var r = parseInt(rgb[0].split('(')[1]);
        var g = parseInt(rgb[1]);
        var b = parseInt(rgb[2].split(')')[0]);
        var a = isLine ? (Number(rgb[3].split(')')[0]) + 0.2) : Number(rgb[3].split(')')[0])
        return `rgba(${r}, ${g}, ${b}, ${a})`
      }
    }

    const lineData = (type?: string) => {
      return this.items.map((item) => {
        return {
          ...item,
          coords: [item.value, [item.value[0], item.value[1] + item.datas * lineMaxHeight(type)]]
        }
      })
    }

    const scatterData = () => {
      return this.items.map((item) => {
        return [item.value[0], item.value[1] + item.datas * lineMaxHeight(), item.datas]
      })
    }
    // 柱状体的底部
    const scatterData2 = () => {
        return this.items.map((item) => {
          return {
            name: item.name,
            value: item.value,
            datas:item.datas,
          }
        })
    }
    
    const effectOptions =  {
      show: options.mapBarAnimate,
      period: options.mapBarAnimateTime,
      symbol: options.mapBarAnimateSymbolType === 'default' ? options.mapBarAnimateSymbol : `image://${options.mapBarAnimateImage}`,
      // symbol: 'image://',
      symbolSize: [options.mapBarAnimateSymbolWidth, options.mapBarAnimateSymbolHeight], // 图标大小
      color: options.useToBar && options.mapCollection.length ? '' : options.mapBarAnimateSymbolColorType === 'default' ? options.mapBarColor : options.mapBarAnimateSymbolColor,
      delay: 0,
      trailLength: options.mapBarAnimateSymbolTrailLength / 100,
    }

    const setBarData = [{// 柱状体的主干
      type: 'lines',
      zlevel: 5,
      effect: isSymBolChart ?  { show: false } : effectOptions,
      lineStyle: {
        width: options.mapBarWidth, // 尾迹线条宽度
        color: (params: any) => {
          const _value = params.data.datas;
          const _color = options.useToBar ? formatColor(options.mapBarColor, _value) : options.mapBarColor;
          if (options.mapBarClose) return 'rgba(255, 255, 255, 0)';
          return {
            type: 'linear',
            x: 0,
            y: 0,
            x2: 1,
            y2: 0,
            colorStops: [
              {
                offset: 0,
                color: hexToRgba(_color, 0.6),
              },
              {
                offset: 0.2,
                color: hexToRgba(_color, 0.6),
              },
              {
                offset: 0.5,
                color: hexToRgba(getLightOrDarkColor(_color, 0.1, options.symbolStyle === 'diamond'), 1, options.symbolStyle === 'diamond'),
              },
              {
                offset: 0.7,
                color: hexToRgba(getLightOrDarkColor(_color, 0.1, options.symbolStyle === 'diamond'), 1, options.symbolStyle === 'diamond'),
              },
              {
                offset: 1,
                color: hexToRgba(_color, 0.6),
              }
            ],
            global: false // 缺省为 false
          }
        },
        opacity: options.mapBarClose  ? 0 : (options.mapBarAnimate ? 0.1 : 1), // 尾迹线条透明度
        curveness: 0 // 尾迹线条曲直度
      },
      animation:false,
      data: lineData()
    },
    {// 柱状体的主干Label
        type: 'lines',
        zlevel: 6,
        effect: {
          show: false
        },
        lineStyle: {
          with: 0,
          opacity: 0, // 尾迹线条透明度
        },
        label: labelOptions(),
        silent: true,
        animation:false,
        data: lineData('lable')
    },
    // 柱状体的顶部
    {
      type: 'scatter',
      coordinateSystem: 'geo',
      geoIndex: 0,
      zlevel: 7,
      symbol: options.symbolStyle,
      symbolSize: [options.mapBarWidth, options.mapBarWidth / 2],
      itemStyle: {
        color: (params: any) => {
          const _value = params.data[2];
          const _color = options.useToBar? formatColor(options.mapBarColor, _value) : options.mapBarColor;
          return _color; 
        },
        opacity: options.mapBarClose ? 0 : 1
      },
      silent: true,
      data: isSymBolChart ? [] : scatterData()
    },
    // 柱状体的底部
    {
      type: 'scatter',
      coordinateSystem: 'geo',
      geoIndex: 0,
      zlevel: 8,
      // label: {
      //   // 这儿是处理的
      //   formatter: '{b}',
      //   position: 'bottom',
      //   color: '#fff',
      //   fontSize: 12,
      //   distance: 10,
      //   show: false
      // },
      symbol: options.symbolStyle,
      symbolSize: [options.mapBarWidth, options.mapBarWidth / 2],
      itemStyle: {
        color: (params: any) => {
          const _color = options.useToBar ? formatColor(options.mapBarColor, params.data.datas) : options.mapBarColor;
          return options.mapBarClose ? 'rgba(255, 255, 255, 0)' : _color;
        },
        opacity: 1,
        shadowColor: '#000',
        shadowBlur: 5,
        shadowOffsetY: 2,
      },
      silent: true,
      data: isSymBolChart ? [] : scatterData2()
    },
    // 底部外框
    {
      tooltip: {
        show: false,
      },
      type: 'effectScatter',
      coordinateSystem: 'geo',
      geoIndex: 0,
      zlevel: 9,
      label: {
        show: false
      },
      symbol: 'circle',
      symbolSize: [10, 5],
      rippleEffect: {
        scale: options.mapBarBottomAnimate === 'stroke' ?(options.mapBarBottomAnimateSize + 2): options.mapBarBottomAnimateSize,
        brushType: options.mapBarBottomAnimate,
        period: options.mapBarBottomAnimateTime,
      },
      showEffectOn: 'render',
      itemStyle: {
        color: (params: any) => {
          const _value = params.data.datas;
          const _isBarColor = options.mapBarBottomColorType === 'default' ? options.mapBarColor :  options.mapBarBottomAnimateColor;
          const _color = options.useToBar ?  formatColor(_isBarColor, _value) : _isBarColor;
          return {
            type: 'radial',
            x: 0.5,
            y: 0.5,
            r: 0.5,
            colorStops: [
              {
                offset: 0, color: hexToRgba(_color, 0) // 0% 处的颜色
              },
              {
                offset: .75, color: hexToRgba(_color, 0) // 100% 处的颜色
              },
              {
                offset: .751, color: hexToRgba(_color, 1)// 100% 处的颜色
              },
              {
                offset: 1, color: hexToRgba(_color, 1) // 100% 处的颜色
              }
            ],
            global: false // 缺省为 false
          }
        },
        opacity: 1
      },
      silent: true,
      data: isSymBolChart ? [] : (options.mapBarBottomCircle ? scatterData2() : [])
    }];
    
    const setSymbolData = [{
      type: 'effectScatter',
      coordinateSystem: 'geo',
      zlevel: 10,
      label: {
        show: false,
      },
      symbol: 'circle',
      symbolSize: [20, 10],
      rippleEffect: {
        scale: options.mapBarBottomAnimate === 'stroke' ? (options.mapBarBottomAnimateSize):  (options.mapBarBottomAnimateSize - 2),
        brushType: options.mapBarBottomAnimate,
        period: options.mapBarBottomAnimateTime,
      },
      showEffectOn: 'render',
      itemStyle: {
        normal: {
          shadowColor: '#0ff',
          shadowBlur: 10,
          shadowOffsetX: 0,
          shadowOffsetY: 0,
          color: (params: any) => {
            const _value = params.data.datas;
            const _isBarColor = options.mapBarBottomColorType === 'default' ? options.mapBarColor :  options.mapBarBottomAnimateColor;
            const _color = options.useToBar ? formatColor(_isBarColor, _value) : _isBarColor;
            return {
              type: 'radial',
              x: 0.5,
              y: 0.5,
              r: 0.5,
              colorStops: [
                {
                  offset: 0, color: hexToRgba(_color, 0) // 0% 处的颜色
                },
                {
                  offset: .75, color: hexToRgba(_color, 0) // 100% 处的颜色
                },
                {
                  offset: .751, color: hexToRgba(_color, 1)// 100% 处的颜色
                },
                {
                  offset: 1, color: hexToRgba(_color, 1) // 100% 处的颜色
                }
              ],
              global: false // 缺省为 false
            }
          },
        },
      },
      silent: true,
      data: isSymBolChart ? (options.mapBarBottomCircle ? this.items : []) : [],
    },
    {
      type: 'scatter',
      coordinateSystem: 'geo',
      itemStyle: {
        color: '#f00', 
      },
      symbol: function (value, params) {
        if(options.symbolStyle === 'pyramid') {
          return image.pyramid;
        } else {
          return params.data.img;
        }
      },
      symbolSize: [options.mapSymbolWidth, options.mapSymbolHeight],
      symbolOffset: [0, -options.mapSymbolWidth],
      label: labelOptions(),
      z: 99,
      zlevel: 11,
      data: isSymBolChart ?  this.items : [],
    }];
    
    const getSeries = () => {
      switch (options.symbolStyle) {
        case 'circle':
          return setBarData;
        case 'diamond':
         return setBarData;
        case 'pyramid':
          return setSymbolData;
        case 'water':
          return setSymbolData;
        default:
          break;
      }
    }
    

    let mapOption = {
      tooltip: {
        trigger: 'item',
        // padding: [15, 15],
        show: options.showTooltip,
        backgroundColor: 'transparent',
        position(pos) { 
          return myTooltip.getPosOrSize('pos', pos);
        },
        formatter: (params) => {
          // return params.name
          const _toolTip = this.items.find((_item) => {
            const name = _item.name.replace(locationReg, '');
            return name === params.name && _item;
          });
          if (!this.isMock && _toolTip) {
            let _addToolTipText = `${this.locationName}: ${_toolTip.name} \n${this.valuesName}: ${_toolTip.datas}`
            _toolTip.toolTip.map((_text: any, index: number) => {
              _addToolTipText += `\n${this.toolTipName[index]}: ${_text[this.toolTipName[index]]}`
            })
            return myTooltip.getTooltipDom(_addToolTipText)
          }
        },
      },
      grid: {
        top: 0,
        bottom: 0,
        left: 0,
        right: 0
      },
      geo: [{
          map: options.customMap && this.properties.MapJson ? "customMap" : options.mapName,
          zoom: options.zoom,
          roam: false,
          zlevel: 2,
          layoutSize: '95%',
          layoutCenter: [`${50}%`, `${50}%`],
          label: {
            position: 'bottom',
            color: options.mapBarBottomLabelText.color,
            fontSize: parseInt(options.mapBarBottomLabelText.fontSize),
            distance: 20,
            show: options.customMap && this.properties.MapJson ? options.mapBarBottomLabel : false
          },
          itemStyle: {
            normal: {
                areaColor: 'rgba(0,0,0,0.1)',
                // areaColor: 'transparent',
                color: () => {
                  return 'red'
                },
                borderColor: options.mapBorderColor,
                borderWidth: 1,
                shadowColor: options.mapBorderShadowColor,
                shadowBlur: 10,
            },
            emphasis: {
                areaColor: options.emphasisColor,
            }
        },
      }, {
          // bg map
          map: options.customMap && this.properties.MapJson ? "customMap" : options.mapName,
          zoom: options.zoom,
          roam: false,
          zlevel: 1,
          layoutSize: '95%',
          layoutCenter: [`${options.mapShadowX}%`,`${options.mapShadowY}%`],
          // aspectScale: 1.3,
          silent: true,
          itemStyle: {
            normal: {
              areaColor: options.mapShadowColor,
              borderWidth: 0,
            }
          },
          // data: data,
          regions: [{
            name: '南海诸岛',
            itemStyle: {
              opacity: 0,
            },
          }]
        }],
      series: [{
        type: 'map',
        map: options.customMap && this.properties.MapJson ? "customMap" : options.mapName,
        zoom: options.zoom,
        roam: true,
        zlevel: 3,
        layoutSize: '95%',
        layoutCenter: [`${50}%`, `${50}%`],
        label: {
          position: 'bottom',
          color: options.mapBarBottomLabelText.color,
          fontSize: parseInt(options.mapBarBottomLabelText.fontSize),
          distance: 20,
          show: options.customMap && this.properties.MapJson ? options.mapBarBottomLabel : false
        },
        itemStyle: {
          normal: {
              areaColor: options.mapColor,
              borderColor: options.mapBorderColor,
              borderWidth: 1,
              shadowColor: options.mapBorderShadowColor,
              shadowBlur: 10,
          },
          emphasis: {
              areaColor: options.emphasisColor,
          }
        },
      },
      {
        type: 'scatter',
        name: 'bottomScatter',
        coordinateSystem: 'geo',
        itemStyle: {
          color: 'rgba(255, 255, 255, 0)', 
        },
        symbolSize: [options.mapSymbolWidth, options.mapSymbolHeight],
        symbolOffset: [0, -options.mapSymbolWidth],
        label: {
          // 这儿是处理的
          formatter: '{b}',
          position: 'bottom',
          color: options.mapBarBottomLabelText.color,
          fontSize: parseInt(options.mapBarBottomLabelText.fontSize),
          distance: 20,
          show: options.mapBarBottomLabel
        },
        z: 99,
        zlevel: 12,
        silent: true,
        data: this.items,
       },
        ...getSeries(),
      ],
    };
    if(this.firstRender){
      if (this.timerId) clearTimeout(this.timerId);
      this.timerId = setTimeout(() => {
        this.host.eventService.renderFinish();
      }, 1000)
      this.firstRender = false;
    }
    myChart.setOption(mapOption, true);
  }

  public onDestroy() {
    if (this.timer) {
      clearInterval(this.timer);
      this.timer = null;
    }
    if (this.timerId) {
      clearTimeout(this.timerId);
      this.timerId = null;
    }
    this.container.removeEventListener('mousedown', this.mouseDownHandler);
    this.container.removeEventListener('contextmenu', this.contextmenuFunction);
    myChart.dispose();
  }

  public onResize() {
    myChart.resize();
    let renderData = this.isMock ? rawData : this.resultData;
    this.render(renderData);
  }

  public getInspectorHiddenState(options: VisualNS.IVisualUpdateOptions): string[] {
    let properties = options.properties;
    let hiddenStates = [];
    if(!properties.showLabel) {
      [].push.apply(hiddenStates, ['labelBackgroundColor', 'tooltipDistance', 'labelBorderColor', 'tooltipBgBorderColor', 'tooltipBorderRadius', 'labelPadding', 'labelTextStyle', 'showLocation', 'showValue', 'tooltipBackgroundType', 'tooltipBackgroundImage'])
    }
    
    if (properties.symbolStyle == 'pyramid' || properties.symbolStyle == 'water') {
      hiddenStates = hiddenStates.concat(['mapBarClose', 'mapBarColor', 'mapBarWidth', 'mapBarAnimate', 'mapBarAnimateTime','mapBarAnimateImage', 'mapBarAnimateSymbol', 'mapBarAnimateSymbolColorType', 'mapBarAnimateSymbolColor', 'mapBarAnimateSymbolWidth', 'mapBarAnimateSymbolHeight', 'mapBarAnimateSymbolTrailLength', 'mapBarAnimateSymbolType', 'mapBarAnimateSymbol'])
    }

    if (properties.symbolStyle == 'circle' || properties.symbolStyle == 'diamond') {
      hiddenStates = hiddenStates.concat(['mapSymbolWidth', 'mapSymbolHeight', 'tooltipDistance'])
    }

    if (!properties.mapBarBottomCircle) {
      hiddenStates = hiddenStates.concat(['mapBarBottomAnimate', 'mapBarBottomAnimateColor','mapBarBottomColorType', 'mapBarBottomAnimateSize', 'mapBarBottomAnimateTime'])
    }
    if (properties.tooltipBackgroundType == 'color') {
      hiddenStates = hiddenStates.concat(['tooltipBackgroundImage', 'tooltipBgBorderColor'])
    } else {
      hiddenStates = hiddenStates.concat(['labelBackgroundColor', 'tooltipBgBorderColor'])
    }

    if (properties.mapBarAnimateSymbolType == 'default') {
      hiddenStates = hiddenStates.concat(['mapBarAnimateImage'])
    } else {
      hiddenStates = hiddenStates.concat(['mapBarAnimateSymbol', 'mapBarAnimateSymbolColor'])
    }

    if (properties.mapBarAnimateSymbolColorType == 'default') {
      hiddenStates = hiddenStates.concat(['mapBarAnimateSymbolColor'])
    }
    
    if (!properties.mapBarAnimate) {
      hiddenStates = hiddenStates.concat([ 'mapBarAnimateTime','mapBarAnimateImage', 'mapBarAnimateSymbol', 'mapBarAnimateSymbolColorType', 'mapBarAnimateSymbolColor', 'mapBarAnimateSymbolWidth', 'mapBarAnimateSymbolHeight', 'mapBarAnimateSymbolTrailLength', 'mapBarAnimateSymbolType', 'mapBarAnimateSymbol'])
    }
   
    if (properties.mapBarBottomColorType == 'default') {
      hiddenStates = hiddenStates.concat(['mapBarBottomAnimateColor'])
    }

    if (properties.customMap) {
      hiddenStates = hiddenStates.concat(['mapName'])
    } else {
      hiddenStates = hiddenStates.concat(['MapJson'])
    }

    if (!options.properties.showTooltip) {
      hiddenStates = hiddenStates.concat(['tooltipBackgroundColor', 'tooltipWidth', 'tooltipHeight', 'tooltipBorderColor', 'tooltipPadding', 'tooltipTextStyle'])
    }
    return hiddenStates;
  }

  public getActionBarHiddenState(options: VisualNS.IVisualUpdateOptions): string[] {

    return null;
  }

  public export() {
    return myChart.getDataURL({ type: 'png' });
  }
}